package com.douguo.recipe.network;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.ref.SoftReference;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;

import com.douguo.recipe.LoadingActivity;
import com.douguo.recipe.network.Util.OnNetworkCheckProgress;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Paint;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;

public class Util {

	private static final String TAG = "Util";

	public static final String PIC_STRING_DIRECTORY = "/sdcard/Douguo/";
	public static final String NETWORK_CMWAP = "cmwap";
	public static final String NETWORK_UIWAP = "uiwap";
	public static final String NETWORK_CTWAP = "ctwap";
	public static final String NETWORK_NONETWORK = "nonetwork";
	public static final String NETWORK_WIFI = "wifi";

	public static final String PROXY = "10.0.0.172";

	// public static final String NETWORK_EDGE = "EDGE";
	// public static final String NETWORK_WIFI = "WIFI";
	// public static final String NETWORK_GPRS = "GPRS";
	// public static final String NETWORK_HSPA = "HSPA";
	// public static final String NETWORK_UMTS = "UMTS";
	// public static final String NETWORK_UNKNOWN = "unknown";
	//
	public static String networkInfoString = "";// NETWORK_NONETWORK
												// NETWORK_UIWAP NETWORK_CMWAP

	// public static String currentNetworkType = NETWORK_UNKNOWN;

	public static String inputStreamToString(InputStream is) {
		BufferedInputStream bis = new BufferedInputStream(is);
		int buffer;
		StringBuilder strBuilder = new StringBuilder();
		try {
			while ((buffer = bis.read()) != -1) {
				strBuilder.append((char) buffer);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return strBuilder.toString();
	}

	public static Bitmap inputStreamToBitmap(InputStream is) {
		return BitmapFactory.decodeStream(is);
		// SoftReference<Bitmap> refBitmap = new SoftReference<Bitmap>(bitmap);
	}

	public static SoftReference<Bitmap> inputStreamToRefBitmap(InputStream is) {
		Bitmap bitmap = BitmapFactory.decodeStream(is);
		SoftReference<Bitmap> refBitmap = new SoftReference<Bitmap>(bitmap);
		return refBitmap;
	}

	public static void showShortToast(Context context, String text) {
		Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
	}

	public static void showShortToast(Context context, int resId) {
		Toast.makeText(context, context.getString(resId), Toast.LENGTH_SHORT)
				.show();
	}

	public static void showLongToast(Context context, int resId) {
		Toast.makeText(context, context.getString(resId), Toast.LENGTH_LONG)
				.show();
	}
	

	public static void showLongToast(Context context, String text) {
		Toast.makeText(context, text, Toast.LENGTH_LONG).show();
	}

	public static Bitmap readBitmapFromSDCard(String path) {
		return BitmapFactory.decodeFile(path);
	}

	public static Bitmap read80X80BitmapFromSDCard(String path) {
		return readScaledBitmapFromSDCard(path, 80);
	}

	// public static Bitmap read0X80BitmapFromSDCard(String path){
	// return readScaledBitmapFromSDCard(path,80);
	// }
	public static Bitmap read40X40BitmapFromSDCard(String path) {
		return readScaledBitmapFromSDCard(path, 40);
	}

	private static Bitmap readScaledBitmapFromSDCard(String path,
			int scaledWidth) {
		Bitmap srcBitmap = readBitmapFromSDCard(path);
		if (srcBitmap != null) {
			int width = srcBitmap.getWidth();
			int height = srcBitmap.getHeight();
			int desWidth = width;
			if (height < width) {
				desWidth = height;
			}
			Bitmap desBitmap = Bitmap.createBitmap(srcBitmap,
					(width - desWidth) / 2, (height - desWidth) / 2, desWidth,
					desWidth);
			if (!desBitmap.equals(srcBitmap)) {
				srcBitmap.recycle();
			}
			Bitmap finalBitmap = Bitmap.createScaledBitmap(desBitmap,
					scaledWidth, scaledWidth, true);
			if (!desBitmap.equals(finalBitmap)) {// for safe
				desBitmap.recycle();
			}
			return finalBitmap;
		}
		return null;
	}
	
//	public static void createDirNoMedia(String directory){
//		String noMediaFile = directory+".nomedia";
//		File file = new File(noMediaFile);
//		file.mkdirs();
//		try {
//			file.createNewFile();
//		} catch (IOException e) {
//			Log.e(TAG, "create .nomedia fail");
//		}
//		
//	}
	
	private static void saveBitmapToSDCard(Bitmap bitmap,String url,boolean canSearch) {
		String fileNomediaPath = PIC_STRING_DIRECTORY + ".nomedia";
		File file = new File(url);
		File parentFile = file.getParentFile();
		File nomediaFile = new File(fileNomediaPath);
		if(parentFile != null && !parentFile.exists()){
			parentFile.mkdirs();
		}
		if(!canSearch && !nomediaFile.exists()){
			try {
				nomediaFile.createNewFile();
			} catch (IOException e) {
			}
		}
		if (!file.exists()) {
//			file.getParentFile().mkdirs();
			try {
				file.createNewFile();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				// e.printStackTrace();
			}
		}
		FileOutputStream fos;
		try {
			fos = new FileOutputStream(file);
			bitmap.compress(CompressFormat.JPEG, 100, fos);
			fos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
		}
	}

	//PARAMS: cansearch : can be search by gallery
	// RETURN: return null while error occurs
	public static String saveBitmapToSDCard(Bitmap bitmap,boolean canSearch) {
		String filename = String.valueOf(System.currentTimeMillis());
		String filePath = PIC_STRING_DIRECTORY + filename + ".jpg";
		saveBitmapToSDCard(bitmap,filePath,canSearch);
		return filePath;
	}
	
	public static String saveBitmapToSDCardFromUrl(Bitmap bitmap,String url,boolean canSearch) {
		String filePath = PIC_STRING_DIRECTORY + EncoderByMd5(url) + ".jpg";
		Log.d(TAG, filePath);
		saveBitmapToSDCard(bitmap,filePath,canSearch);
		Log.d(TAG, "save :" +filePath);
		return filePath;
	}

	// public static String getNetworkType(Context ctx) {
	// SharedPreferences sp = ctx.getSharedPreferences(
	// Constant.PREFERENCES_STATE, Context.MODE_PRIVATE);
	// return sp.getString(Constant.PREFERENCES_STATE_NETWORK,
	// "");
	// }
	// return whether the networkType is change
	public static boolean updateNetworkType(Context ctx) {
		ConnectivityManager connectivity = (ConnectivityManager) ctx
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		int preferencesType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
		String networkInfo = NETWORK_NONETWORK;
		if (connectivity == null) {
			// Log.e(Constants.TAG, "获取网络类型失败");
			preferencesType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
		} else {
			NetworkInfo info = connectivity.getActiveNetworkInfo();
			if (info == null) {
				// Log.e(Constants.TAG, "获取网络类型失败");
				preferencesType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
			} else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
				TelephonyManager tm = (TelephonyManager) ctx
						.getSystemService(Context.TELEPHONY_SERVICE);
				int type = tm.getNetworkType();
				// switch (type) {
				// case TelephonyManager.NETWORK_TYPE_EDGE:
				//
				// // Log.d(Constants.TAG, "网络类型为EDGE");
				// break;
				// case TelephonyManager.NETWORK_TYPE_GPRS:
				// // Log.d(Constants.TAG, "网络类型为GPRS");
				// break;
				// case TelephonyManager.NETWORK_TYPE_UMTS:
				// // Log.d(Constants.TAG, "网络类型为UMTS");
				// break;
				// case TelephonyManager.NETWORK_TYPE_UNKNOWN:
				// // Log.d(Constants.TAG, "网络类型未知");
				// break;
				// }
				preferencesType = type;
			} else if (info.getType() == ConnectivityManager.TYPE_WIFI) {
				// Log.d(Constants.TAG, "网络类型为WIFI");
				networkInfo = NETWORK_WIFI;// regard
				preferencesType = ConnectivityManager.TYPE_WIFI;
				// wifi
				// as
				// hspa
			}
		}

		NetworkInfo mobNetInfo = connectivity
				.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
		// Log.d(TAG, networkInfo);
		if (mobNetInfo != null && mobNetInfo.getExtraInfo() != null) {
			networkInfo = mobNetInfo.getExtraInfo();
			// Log.d(TAG, networkInfo+"1");
		}
		if (networkInfo != NETWORK_WIFI
				&& preferencesType == TelephonyManager.NETWORK_TYPE_UNKNOWN) {
			networkInfo = NETWORK_NONETWORK;
			// Log.d(TAG, networkInfo+"2");
		}
		boolean flag = true;
		if (networkInfoString.equals(networkInfo)) {
			flag = false;
		}
		// Log.d(TAG, networkInfo);
		networkInfoString = networkInfo;
		return flag;
	}
	
	
	public static boolean isConnected() {
		return !networkInfoString.equals(NETWORK_NONETWORK);
	}

	public static boolean isUseNetworkPreferences(Context context) {
		return readSettingPreferences(context, "usenetwork_preference", true);
	}

	public static boolean isDownloadPhotoPreferences(Context context) {
		return readSettingPreferences(context, "downloadphoto_preference", true);
	}

//	public static boolean isDownloadPicPreferences(Context context) {
//		return readSettingPreferences(context, "downloadpic_preference", true);
//	}

	private static boolean readSettingPreferences(Context context, String key,
			boolean defaultValue) {
		SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		boolean bool = pref.getBoolean(key, defaultValue);
		return bool;
	}
	
	public static void setUseNetworkPreferences(Context context,boolean value) {
		setSettingPreferences(context, "usenetwork_preference", value);
	}
	
	public static void setDownloadPhotoPreferences(Context context,boolean value) {
		setSettingPreferences(context,"downloadphoto_preference",value);
	}
	
	
	private static void setSettingPreferences(Context context, String key,
			boolean value) {
		SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		pref.edit().putBoolean(key, value).commit();
	}
	

	public static int dip2px(Context context, float dipValue) {
		final float scale = context.getResources().getDisplayMetrics().density;

		return (int) (dipValue * scale + 0.5f);

	}

	public static int px2dip(Context context, float pxValue) {

		final float scale = context.getResources().getDisplayMetrics().density;
		Log.d(TAG, "" + scale);
		return (int) (pxValue / scale + 0.5f);

	}

	private static final Uri PREFERRED_APN_URI = Uri
			.parse("content://telephony/carriers/preferapn");
	private static final String TEST_URL = "http://www.baidu.com";
	public static String proxy;
	public static String port;

	public static void readProxyAndPort(Context context) {
		SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(context);
		proxy = pref.getString("proxy", "");
		port = pref.getString("port", "");
		Log.d(TAG, "proxy: " + proxy);
		Log.d(TAG, "port: " + port);
	}

	public static void initNetwork(Context context) {

		ConnectivityManager connectivity = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		if (connectivity != null) {
			NetworkInfo info = connectivity.getActiveNetworkInfo();
			if (info != null) {
				// 1、check wifi
				if (info.getType() == ConnectivityManager.TYPE_WIFI) {
					saveApn(context, "", "");
					Log.d(TAG, "wifi");
					return;

				}
				// 2、check if is 3g network
				else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
					TelephonyManager tm = (TelephonyManager) context
							.getSystemService(Context.TELEPHONY_SERVICE);
					int type = tm.getNetworkType();
					switch (type) {
					case TelephonyManager.NETWORK_TYPE_EVDO_0:
					case TelephonyManager.NETWORK_TYPE_EVDO_A:
					case TelephonyManager.NETWORK_TYPE_HSDPA:
					case TelephonyManager.NETWORK_TYPE_HSPA:
					case TelephonyManager.NETWORK_TYPE_HSUPA:
					case TelephonyManager.NETWORK_TYPE_1xRTT:
					case TelephonyManager.NETWORK_TYPE_UMTS:
						saveApn(context, "", "");
						Log.d(TAG, "3g");
						return;
					}
				}
				// 3、check hasNotworkSetting
				SharedPreferences pref = PreferenceManager
						.getDefaultSharedPreferences(context);
				String hasNetworkSetting = pref.getString("hasNetworkSetting",
						"false");
				if (hasNetworkSetting.equals("true")) {
					Log.d(TAG, "hasNetworkSetting");
					
					return;
				}
			}
		}
		// 4、readAndSaveApn
		readAndSaveApn(context, true);
		Log.d(TAG, "apn");
	}

	public static boolean checkNetwork(Context context, OnNetworkCheckProgress progress) {

		writeSettingPreferences(context, new String[] { "hasNetworkSetting" },
				new String[] { "true" });

		// 1、use system apn setting
		String[] apnStr = readAndSaveApn(context, false);
		Log.d(TAG, "checkNetwork 1");
		progress.update(10);
		if (apnStr != null) {
			if (testNetwork(context, apnStr[0], apnStr[1])) {
				saveApn(context, apnStr[0], apnStr[1]);
				progress.update(100);
				return true;
			}
		}
		progress.update(30);
		// 2、without setting proxy
		Log.d(TAG, "checkNetwork 2");
		if (testNetwork(context, null, null)) {
			saveApn(context, "", "");
			progress.update(100);
			return true;
		}
		progress.update(60);
		// 3、use definated apn
		String[] apnProxy = context.getResources().getStringArray(
				com.douguo.recipe.R.array.apn_proxy);
		String[] apnPort = context.getResources().getStringArray(
				com.douguo.recipe.R.array.apn_port);
		int i = 0;
		Log.d(TAG, "checkNetwork 3");
		for (String proxy : apnProxy) {
			if (testNetwork(context, proxy, apnPort[i])) {
				saveApn(context, proxy, apnPort[i++]);
				readProxyAndPort(context);
				progress.update(100);
				return true;
			}
		}
		progress.update(100);
		return false;

	}

	private static final int CONNECT_TIMEOUT = 10000;
	private static final int SO_TIMEOUT = 10000;

	private static boolean testNetwork(Context context, String proxyStr,
			String portStr) {
		HttpClient client = new DefaultHttpClient();
		client.getParams().setParameter(
				CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECT_TIMEOUT);
		client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
				SO_TIMEOUT);
		if (proxyStr != null && portStr != null && !proxyStr.equals("")
				&& !portStr.equals("")) {
			HttpHost proxy = new HttpHost(Util.PROXY, Integer.valueOf(portStr),
					"http");
			client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
					proxy);
		}
		HttpGet hg = new HttpGet(TEST_URL);
		try {
			HttpResponse rsp = client.execute(hg);
			if (rsp.getStatusLine().getStatusCode() == 200) {
				return true;
			}
		} catch (Exception e) {
			return false;
		}
		return false;
	}

	public static String[] readAndSaveApn(Context context,
			boolean isSaveToSharePreference) {
		Cursor cursor = context.getContentResolver().query(PREFERRED_APN_URI,
				null, null, null, null);
		cursor.moveToFirst();
		if (cursor.isAfterLast()) {
			return null;
		}
		String proxy = cursor.getString(cursor.getColumnIndex("proxy"));
		String port = cursor.getString(cursor.getColumnIndex("port"));
		if (proxy != null && port != null && isSaveToSharePreference) {
			saveApn(context, proxy, port);
		}
		cursor.close();
		return new String[] { proxy, port };
	}

	private static void saveApn(Context context, String proxy, String port) {
		writeSettingPreferences(context, new String[] { "proxy", "port" },
				new String[] { proxy, port });
	}
	
	public static byte[] Bitmap2Bytes(Bitmap bm){  
	    ByteArrayOutputStream baos = new ByteArrayOutputStream();    
	    bm.compress(Bitmap.CompressFormat.PNG, 100, baos);    
	    return baos.toByteArray();  
	} 
	


	private static void writeSettingPreferences(Context context, String[] keys,
			String[] values) {
		if (keys != null && values != null) {
			SharedPreferences pref = PreferenceManager
					.getDefaultSharedPreferences(context);
			Editor editor = pref.edit();
			int i = 0;
			for (String key : keys) {
				editor.putString(key, values[i++]);
			}
			editor.commit();
		}
	}

	public interface OnNetworkCheckProgress {
		public void update(int progressValue);
	}
	
	public static Bitmap readCachePhoto(String url) {
		Bitmap bm = null;
		if(url != null){
		String filepath = PIC_STRING_DIRECTORY + EncoderByMd5(url) + ".jpg";
			Log.d(TAG, filepath);
			bm = readBitmapFromSDCard(filepath);
		}
		return bm;
	}
	
	  /**利用MD5进行加密
     * @param str  待加密的字符串
     * @return  加密后的字符串(maybe null)
     * @throws NoSuchAlgorithmException  没有这种产生消息摘要的算法
     * @throws UnsupportedEncodingException  
     */
    public static String EncoderByMd5(String str){
        //确定计算方法
        MessageDigest md5;
        String newstr = null;
		try {
			md5 = MessageDigest.getInstance("MD5");
			BASE64Encoder base64en = new BASE64Encoder();
	        //加密后的字符串
	        newstr=base64en.encode(md5.digest(str.getBytes("utf-8")));
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        return newstr;
    }
    
    


}

/**
 * @author yovn
 * 
 */
class BASE64Encoder {

    private static char[] codec_table = { 'A', 'B', 'C', 'D', 'E', 'F', 'G',
            'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
            'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
           'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
           'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6',
            '7', '8', '9', '+', '/' };

    public BASE64Encoder() {

    }

    public String encode(byte[] a) {
        int totalBits = a.length * 8;
        int nn = totalBits % 6;
        int curPos = 0;// process bits
        StringBuffer toReturn = new StringBuffer();
        while (curPos < totalBits) {
            int bytePos = curPos / 8;
            switch (curPos % 8) {
            case 0:
                toReturn.append(codec_table[(a[bytePos] & 0xfc) >> 2]);
                break;
            case 2:

                toReturn.append(codec_table[(a[bytePos] & 0x3f)]);
                break;
            case 4:
                if (bytePos == a.length - 1) {
                    toReturn
                            .append(codec_table[((a[bytePos] & 0x0f) << 2) & 0x3f]);
                } else {
                    int pos = (((a[bytePos] & 0x0f) << 2) | ((a[bytePos + 1] & 0xc0) >> 6)) & 0x3f;
                    toReturn.append(codec_table[pos]);
                }
                break;
            case 6:
                if (bytePos == a.length - 1) {
                    toReturn
                            .append(codec_table[((a[bytePos] & 0x03) << 4) & 0x3f]);
                } else {
                    int pos = (((a[bytePos] & 0x03) << 4) | ((a[bytePos + 1] & 0xf0) >> 4)) & 0x3f;
                    toReturn.append(codec_table[pos]);
                }
                break;
            default:
                //never hanppen
                break;
            }
            curPos+=6;
        }
        if(nn==2)
        {
            toReturn.append("==");
        }
        else if(nn==4)
        {
            toReturn.append("=");
        }
        return toReturn.toString();

    }

}
